import 'dart:async';
import 'dart:isolate';

import 'package:flutter_track/base/base_logger.dart';
import 'package:flutter_track/base/tracker_message_bean.dart';
import 'package:flutter_track/tracker_isolate/tracker_worker_ffi.dart';

class TrackerWorkerIsolate {
  /// woker isolate 应该要做的东西
  /// mainSendPort 初始状态发送的 main isolate 所能接收的端口
  /// isolate must run on top level static mehtod...
  static void trackerActionWithPort(SendPort mainSendPort) {
    var microTrackerTag = "micro_task_send_tag";

    /// 发送tracker的接收到mainisolate中，用于双向信息发送
    var trackerReceivePort = ReceivePort("tracker_receive_port");
    mainSendPort.send(trackerReceivePort.sendPort);
    ActionMessage? lastSendMessage;

    /// 任务调度器
    Timer? scheduleTimer;

    /// 基础dart代码偏移量
    String baseDartIsolate = "";

    /// 基础vm的偏移
    String baseVmIstructions = "";

    /// 超时堆栈记录调度器
    Timer? trackerTimer;

    bool isOuttime = false;

    /// 任务发起调度时间
    int scheduleMicroSec = 1000;

    /// 超时任务堆栈记录时间
    int trackMicroSec = 200;

    trackerReceivePort.listen((message) {
      if (message is ActionMessage) {
        switch (message.action) {
          case SendAction.microTaskDone:
            Log.info(
              tag: microTrackerTag,
              message: "receive micro task done..",
            );
            lastSendMessage = null;

            /// 如若超时，重新发送调度任务，否则不处理
            if (isOuttime) {
              Future.delayed(const Duration(seconds: 1)).then((value) {
                trackerTimer?.cancel();
                scheduleTimer?.cancel();
                trackerReceivePort.sendPort.send(
                  ActionMessage(
                    action: SendAction.shouldSendMicroTask,
                    msg: "$baseDartIsolate#$baseVmIstructions",
                  ),
                );
              }).whenComplete(() {
                  
              });
            }
            break;
          case SendAction.exit:
            TrackerWorkerFFI.releaseFFI();
            scheduleTimer?.cancel();
            trackerTimer?.cancel();
            lastSendMessage = null;
            ActionMessage newMessage = message.copy();
            newMessage.msg = "isolate should exit.";
            mainSendPort.send(newMessage);
            trackerReceivePort.close();
            break;

          case SendAction.shouldSendMicroTask:

            /// 理论上，从这里开始进行自动tracker。如若多次调用，则会抛弃上一次执行的tracker
            scheduleTimer?.cancel();
            trackerTimer?.cancel();
            lastSendMessage = null;
            isOuttime = false;
            var baseSplits = message.msg?.split("#");

            baseDartIsolate = baseSplits?.first ?? "";
            baseVmIstructions = baseSplits?.last ?? "";
            Log.printAndroidLogger(
              "worker isolate.. base dart isolate: $baseDartIsolate",
            );

            /// 进入轮训调度
            scheduleTimer = Timer.periodic(
              Duration(milliseconds: scheduleMicroSec),
              (timer) {
                if (lastSendMessage != null) {
                  /// 关闭外层调度timer，执行里层timer
                  scheduleTimer?.cancel();
                  isOuttime = true;
                  trackerTimer = Timer.periodic(
                    Duration(milliseconds: trackMicroSec),
                    (timer) {
                      /// 这里是子 isolate 中，理论上应该在此进行调用cpp方法进行任务处理
                      /// DynamicLibrary fflib = DynamicLibrary.open('');
                      /// todo 由于子 isolate 无法通过调用methodchannel 从而无法调用jni，无法调用cpp方法，因此考虑直接从dart调用cpp方法
                      /// todo 需要生成so库，优先构建cpp项目
                      TrackerWorkerFFI.doCppTrack(
                        int.tryParse(baseDartIsolate) ?? 0,
                        int.tryParse(baseVmIstructions) ?? 0,
                      );
                    },
                  );
                } else {
                  isOuttime = false;
                  Log.info(
                    tag: microTrackerTag,
                    message: "worker send micro task... ",
                  );

                  /// 定期发送任务请求， 目前仅仅打印日志
                  lastSendMessage = ActionMessage(
                    action: SendAction.sendMicroTask,
                  );
                  mainSendPort.send(lastSendMessage);
                }
              },
            );
            break;
          default:
            break;
        }
      } else {
        Log.info(
          tag: microTrackerTag,
          message:
              "unknow message: $message, current isolate:${Isolate.current.debugName}",
        );
      }
    });
  }
}
